package com.yunhe.common.websocket;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.yunhe.common.exception.code.ErrorCode;
import com.yunhe.common.model.ResultObject;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * WebSocket消息封装类
 * @author liuronglei
 */
@Service
public class WebsocketIncrementThread {
    private ObjectMapper mapper = new ObjectMapper();
    private static final Logger logger = LoggerFactory.getLogger(WebsocketIncrementThread.class);

    /**
     * 往session发送内容_加锁
     * @param session session对象
     * @param textMessage 发送的内容
     */
    private void sendMessage(WebSocketSession session, TextMessage textMessage) throws IOException {
        synchronized (session) {
            session.sendMessage(textMessage);
        }
    }

    /**
     * 发送数据_[item]形式
     */
    void sendMessageList(WebSocketSession session, List<?> result) {
        if (result != null) {
            try {
                List<Object> sendList = new ArrayList<>();
                if (result.size() == 0) {
                    // size为0时，也需要发送给客户端
                    sendMessage(session, new TextMessage(mapper.writeValueAsString(sendList)));
                } else {
                    int hasBeenSent = 0;
                    int length = 0;
                    while (hasBeenSent < result.size()) {
                        Object obj = result.get(hasBeenSent++);
                        length += mapper.writeValueAsString(obj).length();
                        // 65535为最大长度，5000为预留长度，sendList.size为对象间隔的逗号
                        if (length > 65535 - 5000 - sendList.size()) {
                            sendMessage(session, new TextMessage(mapper.writeValueAsString(sendList)));
                            length = 0;
                            sendList.clear();
                        }
                        sendList.add(obj);
                        if (hasBeenSent == result.size()) {
                            sendMessage(session, new TextMessage(mapper.writeValueAsString(sendList)));
                            length = 0;
                            sendList.clear();
                        }
                    }
                }
            } catch(IOException e) {
                logger.error("WebSocket连接向客户端发送内容时，序列化对象出错：{}", result.toString());
                e.printStackTrace();
            }
        }
    }

    /**
     * 发送数据_<Key, List>形式
     */
    void sendMessageListMap(WebSocketSession session, Map<Object, List<?>> resultMap) {
        if (resultMap != null && resultMap.size() > 0) {
            resultMap.forEach((point, result) -> {
                if (result != null) {
                    Map<Object, List<?>> sendResult = new HashMap<>();
                    try {
                        List<Object> sendList = new ArrayList<>();
                        sendResult.put(point, sendList);
                        if (result.size() == 0) {
                            // size为0时，也需要发送给客户端
                            sendMessage(session, new TextMessage(mapper.writeValueAsString(sendResult)));
                        } else {
                            int hasBeenSent = 0;
                            int length = 0;
                            while (hasBeenSent < result.size()) {
                                Object obj = result.get(hasBeenSent++);
                                length += mapper.writeValueAsString(obj).length();
                                // 65535为最大长度，5000为预留长度，sendList.size为对象间隔的逗号
                                if (length > 65535 - 5000 - sendList.size()) {
                                    sendMessage(session, new TextMessage(mapper.writeValueAsString(sendResult)));
                                    length = 0;
                                    sendList.clear();
                                }
                                sendList.add(obj);
                                if (hasBeenSent == result.size()) {
                                    sendMessage(session, new TextMessage(mapper.writeValueAsString(sendResult)));
                                    length = 0;
                                    sendList.clear();
                                }
                            }
                        }
                    } catch(IOException e) {
                        logger.error("WebSocket连接向客户端发送内容时，序列化对象出错：{}", result.toString());
                        e.printStackTrace();
                    }
                }
            });
        }
    }

    /**
     * 发送数据_<Key, Object>形式
     */
    void sendMessageObjectMap(WebSocketSession session, Map<Object, Object> result) throws IOException {
        if (result != null && result.size() > 0) {
            int length = mapper.writeValueAsString(result).length();
            if (length <= 65535) {
                sendMessage(session, new TextMessage(mapper.writeValueAsString(result)));
            } else {
                //result中单个数据的最大长度
                int maxSingleLen = 0;
                for (Map.Entry<Object, Object> entry : result.entrySet()) {
                    int max;
                    if ((max = mapper.writeValueAsString(entry.getKey()).length() + mapper.writeValueAsString(entry.getValue()).length() + 1) > maxSingleLen) {
                        maxSingleLen = max;
                    }
                }
                // 每次发送的最大数量
                int count = (65535 - 5000) / maxSingleLen;
                int i = 0;
                Map<Object, Object> map = new HashMap<>(count);
                for (Map.Entry<Object, Object> entry : result.entrySet()) {
                    i++;
                    if (i <= count) {
                        map.put(entry.getKey(), entry.getValue());
                    } else {
                        i = 0;
                        sendMessage(session, new TextMessage(mapper.writeValueAsString(map)));
                        map.clear();
                    }
                }
                if (map.size() > 0) {
                    sendMessage(session, new TextMessage(mapper.writeValueAsString(map)));
                    map.clear();
                }
            }
        }
    }

    /**
     * 发送数据
     */
    void sendMessage(WebSocketSession session, Object point, Object result) throws IOException {
        Map<Object, Object> sendResult = new HashMap<>();
        sendResult.put(point, result);
        sendMessage(session, new TextMessage(mapper.writeValueAsString(sendResult)));
    }

    /**
     * 发送数据
     */
    void sendMessage(WebSocketSession session, Object data) throws IOException {
        sendMessage(session, new TextMessage(mapper.writeValueAsString(data)));
    }

    /**
     * 发送错误
     */
    void sendError(WebSocketSession session, ErrorCode.CODE errorCode) throws IOException {
        sendMessage(session, new TextMessage(mapper.writeValueAsString(new ResultObject<>(
                errorCode.value(), ErrorCode.CODE.METHOD_ARGUMENT_NOTVALID.title()))));
    }

}